#pragma once

#include "../utils/misc.h"

namespace mdtx::online::impl
{
    template <typename T>
    class macd
    {
    public:
        T a, cd{}, sig{}, hist{};
        kahan<T> acc_sig{};
        bool init{};

        explicit macd(T alpha)
            : a(alpha)
        {
        }

        void insert_impl(T mfast, T mslow)
        {
            cd = mfast - mslow;
            if (init)
                [[likely]]
            {
                acc_sig(sig, (cd - sig) * a);
            }
            else
                [[unlikely]]
            {
                sig = cd;
                init = true;
            }
            hist = cd - sig;
        }

        void reset_impl()
        {
            init = false;
            cd = sig = hist = 0;
            acc_sig.reset();
        }
    };

    template <typename T>
    class rsi
    {
    public:
        T a, m_gain{}, m_loss{};
        kahan<T> acc_gain{}, acc_loss{};
        bool init{};

        explicit rsi(T alpha)
            : a(alpha)
        {
        }

        void insert_impl(T x, T xbl)
        {
            T gain = small_number(x);
            T loss = small_number(x);
            if (x > xbl)
            {
                gain = x - xbl;
            }
            else if (x < xbl)
            {
                loss = xbl - x;
            }
            if (init)
                [[likely]]
            {
                acc_gain(m_gain, a * (gain - m_gain));
                acc_loss(m_loss, a * (loss - m_loss));
            }
            else
                [[unlikely]]
            {
                m_gain = gain;
                m_loss = loss;
                init = true;
            }
        }

        void reset_impl()
        {
            init = false;
            m_gain = m_loss = 0;
            acc_gain.reset();
            acc_loss.reset();
        }
    };

}
